import { CPagination } from './components/CPagination'
import { DataFilter, Filter } from './components/DataFilter'
import { autoload as load } from '@cydon/ui'
import { getLocation } from 'random_chinese_fantasy_names'

/** 自动加载组件 */
export const autoload = (el = document.body) =>
	load(el, name => import(`./components/${name}.ts`))
		.catch(e => {
			console.error(e)
		})

/** 随机生成一个名字 */
export const pickName = () => getLocation(1)[0].name

// 纯函数

export const u = (x: number) => Math.max(0, x)

export const hexColor = (col: number[]) =>
	col.map(x => (x * 255 | 0).toString(16).padStart(2, '0')).join('')

/** 过滤和排序数据 */
function applyFilter<T extends Record<string, any>>(f: DataFilter, items: T[]) {
	if (f.filters?.length)
		items = items.filter(item => shouldShow(f.filters, item))
	if (f.sortKeys.length)
		items = items.sort((a, b) => {
			let r = 0
			for (const { index: i, dir } of f.sortKeys) {
				if (dir == 5)
					r = Math.random() - 0.5
				else {
					const x = a[f.keys[i]], y = b[f.keys[i]]
					r = dir > 2 ? y.length - x.length : y - x
					if (dir & 1) r = -r
				}
				if (r) break
			}
			return r
		})
	return items
}

export function processData<T extends Record<string, any>>(
	items: T[], p: CPagination, f?: DataFilter) {
	if (f)
		items = applyFilter(f, items)
	p.data.total = items.length
	const i = p.pageNum - 1,
		n = p.perPage
	return items.slice(i * n, i * n + n)
}

function shouldShow(filters: Filter[], item: Record<string, any>) {
	let show = +!filters.length, lastconj = 3
	for (const filter of filters) {
		const { key, op, value, conj, valid } = filter
		if (valid) {
			const val = item[key]
			const cond = +(op < 2 ? val + '' == value :
				op < 4 ? (typeof val == 'number' ?
					val > +value : value.localeCompare(val) < 0) :
					op < 6 ? (typeof val == 'number' ?
						val >= +value : value.localeCompare(val) <= 0) :
						op < 8 ? (val + '').includes(value) :
							RegExp(value).test(val)
			) ^ (op & 1)
			if (lastconj > 2) show = cond
			else if (lastconj == 0)
				show! &= cond
			else if (lastconj == 1)
				show! |= cond
			else
				show! ^= cond
		}
		lastconj = conj
	}

	return show
}
